#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2024 Bardia Moshiri <fakeshell@bardia.tech>

# Basic help function
help() {
  cat <<EOF
batman, a battery management program originally intended for Droidian

Usage: batman
EOF
  exit 0
}

# Bumped at every commit
version() {
   echo "1.43"
   exit 0
}

if [ -r "/dev/tty0" ]; then
    delay() {
        read -rt "$1" < /dev/tty0
    }
else
    delay() {
        sleep "$1"
    }
fi

# First check if user is asking for help or version if not move on.
case "$1" in
  -h|-\?|--help)
    help
    ;;
  -v|--version)
    version
    ;;
esac

# FIRSTPOL will get the first policy group. (this group stores LITTLE cores)
# FIRSTPOLCORE will get the first cpu core of policy group one.
# LASTPOLCORE will get the last cpu core of policy group one.
CORE_FIRST=$(awk '$1 == "processor" {print $3; exit}' /proc/cpuinfo)
CORE_LAST=$(awk '$1 == "processor" {print $3}' /proc/cpuinfo | tail -1)
UIDS=$(ls /run/user | head -1)
ARCH=$(uname -m)

# x86 cpus have powersave and performance governors, check architecture and set the governor accordingly.
if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
   if grep -q "performance" /sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_available_governors; then
      if grep -q "powersave" /sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_governor; then
         DEFAULT_GOVERNOR="powersave"
      else
         DEFAULT_GOVERNOR="performance"
      fi
   else
      echo "can't find the right governor. exiting"
      exit 0
   fi
else
   DEFAULT_GOVERNOR=$(</sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_governor)
fi

AVUSER=$(ls /run/user | wc -l)
AVPOL=$(ls /sys/devices/system/cpu/cpufreq | grep -c policy)

# Exynos chips require special configuration and governors, usually device tree has the chipset name in the model section.
if [ -f /proc/device-tree/model ]; then
    if grep -q -i "EXYNOS" /proc/device-tree/model; then
       IS_EXYNOS=true
    else
       IS_EXYNOS=false
    fi
fi

# Make sure the required directory exists.
[ ! -d /var/lib/batman/ ] && mkdir -p /var/lib/batman/

# Parse our config file.
if [ -f /etc/batman/config ]; then
   CONFIG_FILE=/etc/batman/config
elif [ -f /var/lib/batman/config ]; then
   CONFIG_FILE=/var/lib/batman/config
fi

if [ -n "${CONFIG_FILE}" ]; then
   echo "Parsing ${CONFIG_FILE}"
   source <(tail -n +2 "${CONFIG_FILE}")
else
   echo "config file does not exist. using default values"
fi

# Check if there are any policies available.
if [ "${AVPOL}" != "0" ]; then
   if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
      FIRSTPOL=$(ls /sys/devices/system/cpu/cpufreq | grep policy | head -1)
      FIRSTPOLCORE=1
      LASTPOLCORE="${CORE_LAST}"
   else
      FIRSTPOL=$(ls /sys/devices/system/cpu/cpufreq | grep policy | head -1)
      FIRSTPOLCORE=$(cut -c1 - < /sys/devices/system/cpu/cpufreq/"${FIRSTPOL}"/related_cpus)
      LASTPOLCORE=$(awk '{for(i=NF;i>=1;i--) printf("%s ", $i)}' /sys/devices/system/cpu/cpufreq/"${FIRSTPOL}"/related_cpus | cut -c1 -)
   fi
# Support for older arm devices such as MSM8996.
elif [ "${AVPOL}" = "0" ] && [ -f "/sys/devices/system/cpu/cpufreq/all_time_in_state" ]; then
   LEGACY=true
   FIRSTPOLCORE="${CORE_FIRST}"
   LASTPOLCORE=$((CORE_LAST/2))
else
   echo "no cpu policies available. exiting"
   exit 0
fi

OFFLINE_COUNT="${LASTPOLCORE}"

# this is tricky so lets only use it if port requires it
if [ -f /var/lib/batman/exynos_cpu_limit ]; then
   if [ -f /sys/power/cpufreq_min_limit ]; then
      CPUSAVEGOVERNOR="exynos_cpu_limit"
      CPUFREQ_MIN_LIMIT="$(</sys/power/cpufreq_min_limit)"
      CPUFREQ_MAX_LIMIT="$(</sys/power/cpufreq_max_limit)"
   fi
fi

# Check if powersave governor is available.
if [ "${LEGACY}" = "true" ] && [ -z "${CPUSAVEGOVERNOR}" ]; then
   if grep -q powersave /sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_available_governors; then
      CPUSAVEGOVERNOR="powersave"
   elif grep -q userspace /sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_available_governors; then
      CPUSAVEGOVERNOR="userspace"
   else
      echo "powersave or userspace are not available governors on this system. exiting"
      exit 0
   fi
elif [ -z "${CPUSAVEGOVERNOR}" ]; then
   if grep -q powersave /sys/devices/system/cpu/cpufreq/"${FIRSTPOL}"/scaling_available_governors; then
      CPUSAVEGOVERNOR="powersave"
   elif grep -q userspace /sys/devices/system/cpu/cpufreq/"${FIRSTPOL}"/scaling_available_governors; then
      CPUSAVEGOVERNOR="userspace"
   else
      echo "powersave or userspace are not available governors on this system. exiting"
      exit 0
   fi
fi

if ! which batman-helper > /dev/null 2>&1; then
   echo "batman-helper is not available. exiting"
   exit 0
fi

if eval "XDG_RUNTIME_DIR=/run/user/\$UIDS/ $(which batman-helper) wlrdisplay" &> /var/lib/batman/wlrfirstcheck; then
   echo "using wlrdisplay for screen status"
   GET_SCREEN="XDG_RUNTIME_DIR=/run/user/\$UIDS/ batman-helper wlrdisplay"
   WLR=true
else
   WLR=false
fi

# Check if system is using a wlroots based desktop environment.
if [ "${WLR}" = "true" ]; then
   eval "${GET_SCREEN}" &> /var/lib/batman/wlrcheck

   if grep -q "compositor doesn't support" /var/lib/batman/wlrcheck || grep -q "wl_display_dispatch failed" /var/lib/batman/wlrcheck; then
      WLROOTS=false
   else
      WLROOTS=true
   fi
else
   WLROOTS=false
fi

# Check if wlroots based environment has started. if not wait a bit and retry.
if [ "${WLROOTS}" = "true" ]; then
   while true
   do
      if eval "${GET_SCREEN}" &> /dev/null; then
         break
      else
         delay 10
      fi
   done
# Check if system is using kwin
elif [ "${WLROOTS}" = "false" ] && which kscreen-doctor > /dev/null 2>&1; then
   if XDG_SESSION_TYPE=wayland XDG_RUNTIME_DIR=/run/user/"${UIDS}"/ kscreen-doctor -o 2>/dev/null | grep Output >/dev/null 2>&1; then
      USERNAME=$(id -un "${UIDS}")
      GET_SCREEN="sudo -u $USERNAME DBUS_SESSION_BUS_ADDRESS='unix:path=/run/user/$UIDS/bus' qdbus org.kde.screensaver /ScreenSaver org.freedesktop.ScreenSaver.GetActive"
      KDE=true
   else
      KDE=false
   fi
fi

if [ "${KDE}" = "false" ] && [ "${WLROOTS}" = "false" ]; then
   echo "compositor not supported. exiting"
   exit 0
fi

# make sure only one active user session exists.
if [ "${AVUSER}" -gt "1" ]; then
   echo "more than one user active. waiting for the other user profile to disappear"
   while true
   do
      AVUSER=$(ls /run/user | wc -l)
      if [ "${AVUSER}" -gt "1" ]; then
         delay 10
      else
         echo "other user disappeared. starting"
         break
      fi
   done
fi

if [ -z "$(batman-helper battery)" ]; then
   echo "No battery found in this device. exiting"
   exit 0
fi

if [ -z "${OFFLINE}" ]; then
   echo "Setting the default value of OFFLINE as true"
   OFFLINE=true
fi

if [ "${AVPOL}" -eq "1" ]; then
   echo "Only one cpu policy group detected, disabling cpu offlining"
   OFFLINE=false
fi

if [ -z "${POWERSAVE}" ]; then
   echo "Setting the default value of POWERSAVE as true"
   POWERSAVE=true
fi

if [ -z "${MAX_CPU_USAGE}" ]; then
   echo "Setting the default value of MAX_CPU_USAGE as 60"
   MAX_CPU_USAGE=60
fi

if [ -z "${CHARGESAVE}" ]; then
   echo "Setting the default value of CHARGESAVE as true"
   CHARGESAVE=true
fi

if [ -z "${GPUSAVE}" ]; then
   echo "Setting the default value of GPUSAVE as true"
   GPUSAVE=true
fi

if [ -z "${BUSSAVE}" ]; then
   echo "Setting the default value of BUSSAVE as true"
   BUSSAVE=true
fi

if ! [[ "${MAX_CPU_USAGE}" =~ ^[0-9]+$ ]] || [[ "${MAX_CPU_USAGE}" -lt 0 ]] || [[ "${MAX_CPU_USAGE}" -gt 100 ]]; then
    echo "bad MAX_CPU_USAGE value. defaulting to 60"
    MAX_CPU_USAGE=60
fi

if [ -z "${BTSAVE}" ]; then
   echo "Setting the default value of BTSAVE as true"
   BTSAVE=true
fi

if [ -z "${HYBRIS}" ]; then
   if which batman-hybris > /dev/null 2>&1; then
      echo "batman-hybris is available, setting the default value of LIBPOWER as true"
      LIBPOWER=true
   fi
fi

if [ -z "${WIFI}" ]; then
   if which batman-wifi > /dev/null 2>&1; then
      echo "batman-wifi is available, setting the default value of WIFI as true"
      WIFI=true
   fi
fi

if [ -z "${WAYDROID}" ]; then
   if which batman-waydroid > /dev/null 2>&1; then
      echo "batman-waydroid is available, setting the default value of WAYDROID as true"
      WAYDROID=true
   fi
fi

# Set up an array with the GPU governor file paths to check, can be extended later when more devices are added
gpu_governor_paths=(
  "/sys/class/kgsl/kgsl-3d0/devfreq/governor"
  "/sys/class/kgsl/kgsl-3d0/governor"
  "/sys/class/devfreq/1c00000.qcom,kgsl-3d0/governor"
  "/sys/class/devfreq/5000000.qcom,kgsl-3d0/governor"
  "/sys/class/devfreq/ddr_devfreq/governor"
  "/sys/class/devfreq/graphics/governor"
  "/sys/kernel/gpu/gpu_governor"
  "${DEVFREQ_GPU_PATH}/governor"
)

# Loop through the GPU governor file paths and check if each file exists
for gpu_governor_path in "${gpu_governor_paths[@]}"; do
    if [ -f "$gpu_governor_path" ]; then
       CAN_GPUSAVE=true
       DEFAULT_GPU_GOVERNOR=$(<"$gpu_governor_path")
       GPU_GOVERNOR_PATH="$gpu_governor_path"
       break
    fi
done

[ -z "${DEFAULT_GPU_GOVERNOR}" ] && CAN_GPUSAVE=false

# If powersave is not a governor in the GPU profile then disable this feature.
if [ "${CAN_GPUSAVE}" = "true" ]; then
   if ! grep -q "powersave" "${GPU_GOVERNOR_PATH}"; then
      CAN_GPUSAVE=false
   fi
fi

if ! which bluetoothctl &> /dev/null; then
    echo "bluetoothctl does not exist, setting BTSAVE to false"
    BTSAVE=false
else
    if ! bluetoothctl info | grep -q 'Connected:'; then
        BTSTAT="off"
    else
        BTSTAT="on"
    fi
fi

if ! which waydroid &> /dev/null; then
    echo "Waydroid is not available, disabling waydroid capabilities"
    WAYDROID=false
fi

# Check for bus governor nodes, if available then we'll powersave them too!
if [ -d /sys/class/devfreq/ ]; then
   [ -d /sys/class/devfreq/soc:qcom,cci/ ] && CCI=true && DEFAULT_CCI_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cci/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpubw/ ] && CPUBW=true && DEFAULT_CPUBW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpubw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,gpubw/ ] && GPUBW=true && DEFAULT_GPUBW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,gpubw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,kgsl-busmon/ ] && KGSL_BUSMON=true && DEFAULT_KGSL_BUSMON_GOVERNOR="$(</sys/class/devfreq/soc:qcom,kgsl-busmon/governor)"
   [ -d /sys/class/devfreq/soc:qcom,mincpubw/ ] && MINCPUBW=true && DEFAULT_MINCPUBW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,mincpubw/governor)"
   # [ -d /sys/class/devfreq/soc:qcom,l3-cpu0/ ] && L3CPU0=true && DEFAULT_L3CPU0_GOVERNOR="$(</sys/class/devfreq/soc:qcom,l3-cpu0/governor)"
   # [ -d /sys/class/devfreq/soc:qcom,l3-cpu6/ ] && L3CPU6=true && DEFAULT_L3CPU6_GOVERNOR="$(</sys/class/devfreq/soc:qcom,l3-cpu6/governor)"
   [ -d /sys/class/devfreq/aa00000.qcom,vidc1:arm9_bus_ddr/ ] && VIDC1_ARM9_BUS_DDR=true && DEFAULT_VIDC1_ARM9_BUS_DDR_GOVERNOR="$(</sys/class/devfreq/aa00000.qcom,vidc1:arm9_bus_ddr/governor)"
   [ -d /sys/class/devfreq/aa00000.qcom,vidc:arm9_bus_ddr/ ] && VIDC_ARM9_BUS_DDR=true && DEFAULT_VIDC_ARM9_BUS_DDR_GOVERNOR="$(</sys/class/devfreq/aa00000.qcom,vidc:arm9_bus_ddr/governor)"
   [ -d /sys/class/devfreq/aa00000.qcom,vidc1:bus_cnoc/ ] && VIDC1_BUS_CNOC=true && DEFAULT_VIDC1_BUS_CNOC_GOVERNOR="$(</sys/class/devfreq/aa00000.qcom,vidc1:bus_cnoc/governor)"
   [ -d /sys/class/devfreq/aa00000.qcom,vidc:bus_cnoc/ ] && VIDC_BUS_CNOC=true && DEFAULT_VIDC_BUS_CNOC_GOVERNOR="$(</sys/class/devfreq/aa00000.qcom,vidc:bus_cnoc/governor)"
   # [ -d /sys/class/devfreq/aa00000.qcom,vidc1:venus_bus_ddr/ ] && VENUS_BUS_DDR=true && DEFAULT_VENUSBUSDDR_GOVERNOR="$(</sys/class/devfreq/aa00000.qcom,vidc1:venus_bus_ddr/governor)"
   [ -d /sys/class/devfreq/soc:qcom,l3-cdsp/ ] && L3CDSP=true && DEFAULT_L3CDSP_GOVERNOR="$(</sys/class/devfreq/soc:qcom,l3-cdsp/governor)"
   [ -d /sys/class/devfreq/soc:qcom,memlat-cpu0/ ] && MEMLAT_CPU0=true && DEFAULT_MEMLAT_CPU0_GOVERNOR="$(</sys/class/devfreq/soc:qcom,memlat-cpu0/governor)"
   [ -d /sys/class/devfreq/soc:qcom,memlat-cpu4/ ] && MEMLAT_CPU4=true && DEFAULT_MEMLAT_CPU4_GOVERNOR="$(</sys/class/devfreq/soc:qcom,memlat-cpu4/governor)"
   [ -d /sys/class/devfreq/soc:qcom,memlat-cpu6/ ] && MEMLAT_CPU6=true && DEFAULT_MEMLAT_CPU6_GOVERNOR="$(</sys/class/devfreq/soc:qcom,memlat-cpu6/governor)"
   [ -d /sys/class/devfreq/soc:qcom,mincpu0bw/ ] && MINCPU0BW=true && DEFAULT_MINCPU0BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,mincpu0bw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,mincpu6bw/ ] && MINCPU6BW=true && DEFAULT_MINCPU6BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,mincpu6bw/governor)"
   [ -d /sys/class/devfreq/soc:devfreq_spdm_cpu/ ] && DEVFREQ_SPDM_CPU=true && DEFAULT_DEVFREQ_SPDM_CPU_GOVERNOR="$(</sys/class/devfreq/soc:devfreq_spdm_cpu/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cdsp-cdsp-l3-lat/ ] && CDSP_CDSP_L3_LAT=true && DEFAULT_CDSP_CDSP_L3_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cdsp-cdsp-l3-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu0-cpu-ddr-latfloor/ ] && CPU0_CPU_DDR_LATFLOOR=true && DEFAULT_CPU0_CPU_DDR_LATFLOOR_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu0-cpu-ddr-latfloor/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu0-cpu-l3-lat/ ] && CPU0_CPU_L3_LAT=true && DEFAULT_CPU0_CPU_L3_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu0-cpu-l3-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu0-cpu-llcc-lat/ ] && CPU0_CPU_LLCC_LAT=true && DEFAULT_CPU0_CPU_LLCC_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu0-cpu-llcc-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu0-llcc-ddr-lat/ ] && CPU0_LLCC_DDR_LAT=true && DEFAULT_CPU0_LLCC_DDR_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu0-llcc-ddr-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu6-cpu-ddr-latfloor/ ] && CPU6_CPU_DDR_LATFLOOR=true && DEFAULT_CPU6_CPU_DDR_LATFLOOR_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu6-cpu-ddr-latfloor/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu6-cpu-l3-lat/ ] && CPU6_CPU_L3_LAT=true && DEFAULT_CPU6_CPU_L3_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu6-cpu-l3-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu6-cpu-llcc-lat/ ] && CPU6_CPU_LLCC_LAT=true && DEFAULT_CPU6_CPU_LLCC_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu6-cpu-llcc-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu6-llcc-ddr-lat/ ] && CPU6_LLCC_DDR_LAT=true && DEFAULT_CPU6_LLCC_DDR_LAT_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu6-llcc-ddr-lat/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/ ] && CPU_CPU_LLCC_BW=true && DEFAULT_CPU_CPU_LLCC_BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/ ] && CPU_LLCC_DDR_BW=true && DEFAULT_CPU_LLCC_DDR_BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,npudsp-npu-ddr-bw/ ] && NPUDSP_NPU_DDR_BW=true && DEFAULT_NPUDSP_NPU_DDR_BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,npudsp-npu-ddr-bw/governor)"
   [ -d /sys/class/devfreq/soc:qcom,npu-npu-ddr-bw/ ] && NPU_NPU_DDR_BW=true && DEFAULT_NPU_NPU_DDR_BW_GOVERNOR="$(</sys/class/devfreq/soc:qcom,npu-npu-ddr-bw/governor)"
   [ -d /sys/class/devfreq/17000010.devfreq_mif/ ] && DEVFREQ_MIF=true && DEFAULT_DEVFREQ_MIF_GOVERNOR="$(</sys/class/devfreq/17000010.devfreq_mif/governor)"
   [ -d /sys/class/devfreq/17000020.devfreq_int/ ] && DEVFREQ_INT=true && DEFAULT_DEVFREQ_INT_GOVERNOR="$(</sys/class/devfreq/17000020.devfreq_int/governor)"
   [ -d /sys/class/devfreq/17000030.devfreq_intcam/ ] && DEVFREQ_INTCAM=true && DEFAULT_DEVFREQ_INTCAM_GOVERNOR="$(</sys/class/devfreq/17000030.devfreq_intcam/governor)"
   [ -d /sys/class/devfreq/17000040.devfreq_disp/ ] && DEVFREQ_DISP=true && DEFAULT_DEVFREQ_DISP_GOVERNOR="$(</sys/class/devfreq/17000040.devfreq_disp/governor)"
   [ -d /sys/class/devfreq/17000050.devfreq_cam/ ] && DEVFREQ_CAM=true && DEFAULT_DEVFREQ_CAM_GOVERNOR="$(</sys/class/devfreq/17000050.devfreq_cam/governor)"
   [ -d /sys/class/devfreq/17000060.devfreq_tnr/ ] && DEVFREQ_TNR=true && DEFAULT_DEVFREQ_TNR_GOVERNOR="$(</sys/class/devfreq/17000060.devfreq_tnr/governor)"
   [ -d /sys/class/devfreq/17000070.devfreq_mfc/ ] && DEVFREQ_MFC=true && DEFAULT_DEVFREQ_MFC_GOVERNOR="$(</sys/class/devfreq/17000070.devfreq_mfc/governor)"
   [ -d /sys/class/devfreq/17000080.devfreq_bo/ ] && DEVFREQ_BO=true && DEFAULT_DEVFREQ_BO_GOVERNOR="$(</sys/class/devfreq/17000080.devfreq_bo/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu0_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU0=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU0_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu0_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu1_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU1=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU1_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu1_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu2_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU2=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU2_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu2_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu3_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU3=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU3_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu3_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu4_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU4=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU4_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu4_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu5_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU5=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU5_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu5_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu6_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU6=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU6_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu6_memlat@17000010/governor)"
   [ -d /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu7_memlat@17000010/ ] && GS_MEMLAT_DEVFREQ_MIF_CPU7=true && DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU7_GOVERNOR="$(</sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu7_memlat@17000010/governor)"
fi

declare -A governors=(
  ["GPUSAVE"]="${DEFAULT_GPU_GOVERNOR}"
  ["CCI"]="${DEFAULT_CCI_GOVERNOR}"
  ["CPUBW"]="${DEFAULT_CPUBW_GOVERNOR}"
  ["GPUBW"]="${DEFAULT_GPUBW_GOVERNOR}"
  ["KGSL_BUSMON"]="${DEFAULT_KGSL_BUSMON_GOVERNOR}"
  ["MINCPUBW"]="${DEFAULT_MINCPUBW_GOVERNOR}"
  ["L3CPU0"]="${DEFAULT_L3CPU0_GOVERNOR}"
  ["L3CPU6"]="${DEFAULT_L3CPU6_GOVERNOR}"
  ["VIDC1_ARM9_BUS_DDR"]="${DEFAULT_VIDC1_ARM9_BUS_DDR_GOVERNOR}"
  ["VIDC1_BUS_CNOC"]="${DEFAULT_VIDC1_BUS_CNOC_GOVERNOR}"
  ["VIDC_ARM9_BUS_DDR"]="${DEFAULT_VIDC_ARM9_BUS_DDR_GOVERNOR}"
  ["VIDC_BUS_CNOC"]="${DEFAULT_VIDC_BUS_CNOC_GOVERNOR}"
  ["VENUS_BUS_DDR"]="${DEFAULT_VENUS_BUS_DDR_GOVERNOR}"
  ["L3CDSP"]="${DEFAULT_L3CDSP_GOVERNOR}"
  ["MEMLAT_CPU0"]="${DEFAULT_MEMLAT_CPU0_GOVERNOR}"
  ["MEMLAT_CPU4"]="${DEFAULT_MEMLAT_CPU4_GOVERNOR}"
  ["MEMLAT_CPU6"]="${DEFAULT_MEMLAT_CPU6_GOVERNOR}"
  ["MINCPU0BW"]="${DEFAULT_MINCPU0BW_GOVERNOR}"
  ["MINCPU6BW"]="${DEFAULT_MINCPU6BW_GOVERNOR}"
  ["DEVFREQ_SQPM_CPU"]="${DEFAULT_DEVFREQ_SQPM_CPU_GOVERNOR}"
  ["CDSP_CDSP_L3_LAT"]="${DEFAULT_CDSP_CDSP_L3_LAT_GOVERNOR}"
  ["CPU0_CPU_DDR_LATFLOOR"]="${DEFAULT_CPU0_CPU_DDR_LATFLOOR_GOVERNOR}"
  ["CPU0_CPU_L3_LAT"]="${DEFAULT_CPU0_CPU_L3_LAT_GOVERNOR}"
  ["CPU0_CPU_LLCC_LAT"]="${DEFAULT_CPU0_CPU_LLCC_LAT_GOVERNOR}"
  ["CPU0_LLCC_DDR_LAT"]="${DEFAULT_CPU0_LLCC_DDR_LAT_GOVERNOR}"
  ["CPU6_CPU_DDR_LATFLOOR"]="${DEFAULT_CPU6_CPU_DDR_LATFLOOR_GOVERNOR}"
  ["CPU6_CPU_L3_LAT"]="${DEFAULT_CPU6_CPU_L3_LAT_GOVERNOR}"
  ["CPU6_CPU_LLCC_LAT"]="${DEFAULT_CPU6_CPU_LLCC_LAT_GOVERNOR}"
  ["CPU6_LLCC_DDR_LAT"]="${DEFAULT_CPU6_LLCC_DDR_LAT_GOVERNOR}"
  ["CPU_CPU_LLCC_BW"]="${DEFAULT_CPU_CPU_LLCC_BW_GOVERNOR}"
  ["CPU_LLCC_DDR_BW"]="${DEFAULT_CPU_LLCC_DDR_BW_GOVERNOR}"
  ["NPUDSP_NPU_DDR_BW"]="${DEFAULT_NPUDSP_NPU_DDR_BW_GOVERNOR}"
  ["NPU_NPU_DDR_BW"]="${DEFAULT_NPU_NPU_DDR_BW_GOVERNOR}"
  ["DEVFREQ_MIF"]="${DEFAULT_DEVFREQ_MIF_GOVERNOR}"
  ["DEVFREQ_INT"]="${DEFAULT_DEVFREQ_INT_GOVERNOR}"
  ["DEVFREQ_INTCAM"]="${DEFAULT_DEVFREQ_INTCAM_GOVERNOR}"
  ["DEVFREQ_DISP"]="${DEFAULT_DEVFREQ_DISP_GOVERNOR}"
  ["DEVFREQ_CAM"]="${DEFAULT_DEVFREQ_CAM_GOVERNOR}"
  ["DEVFREQ_TNR"]="${DEFAULT_DEVFREQ_TNR_GOVERNOR}"
  ["DEVFREQ_MFC"]="${DEFAULT_DEVFREQ_MFC_GOVERNOR}"
  ["DEVFREQ_BO"]="${DEFAULT_DEVFREQ_BO_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU0"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU0_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU1"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU1_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU2"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU2_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU3"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU3_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU4"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU4_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU5"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU5_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU6"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU6_GOVERNOR}"
  ["GS_MEMLAT_DEVFREQ_MIF_CPU7"]="${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU7_GOVERNOR}"
)

# Copy default governor to a file to use it later on if the service gets restarted unexpectedly.
if [ ! -f /var/lib/batman/saved ]; then
   if [ "${DEFAULT_GOVERNOR}" = "powersave" ]; then
      if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
         echo "${DEFAULT_GOVERNOR}" > /var/lib/batman/default_cpu_governor
      else
         echo "bad starting governor. exiting"
         exit 0
      fi
   else
      echo "${DEFAULT_GOVERNOR}" > /var/lib/batman/default_cpu_governor
   fi

   for gov in "${!governors[@]}"; do
      if [ "${!gov}" = "true" ]; then
        lowercase=$(echo "${gov,,}") # convert to lowercase
        echo "${governors[$gov]}" > "/var/lib/batman/default_${lowercase}_governor"
      fi
   done

   touch /var/lib/batman/saved
# In case of bad governor values choose the right value or exit if it fails to do so.
elif [ "${DEFAULT_GOVERNOR}" = "powersave" ]; then
   if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
      true
   elif [ "$(</var/lib/batman/default_cpu_governor)"  = "powersave" ]; then
      echo "bad starting governor. exiting"
      exit 0
   else
      DEFAULT_GOVERNOR="$(</var/lib/batman/default_cpu_governor)"
   fi
fi

# Loop over the array and check each variable
for var in "${!governors[@]}"; do
    if [ "${!var}" = "true" ] && [ "${governors[$var]}" = "powersave" ]; then
        if [[ $(<"/var/lib/batman/default_${var,,}_governor") = "powersave" ]]; then
            echo "bad ${var,,} governor. disabling ${var,,} powersave"
            eval "$var=false"
        else
            eval "DEFAULT_${var}_GOVERNOR=$(<"/var/lib/batman/default_${var,,}_governor")"
        fi
    fi
done

if [ -f "/var/lib/batman/CUSTOM_DEFAULT_GOVERNOR" ]; then
   DEFAULT_GOVERNOR="$(</var/lib/batman/CUSTOM_DEFAULT_GOVERNOR)"
   echo "using ${DEFAULT_GOVERNOR} as default governor"
fi

if [ -f "/var/lib/batman/CUSTOM_LASTPOLCORE" ]; then
   LASTPOLCORE="$(</var/lib/batman/CUSTOM_LASTPOLCORE)"
   OFFLINE_COUNT="${LASTPOLCORE}"
   echo "using ${LASTPOLCORE} as last policy core"
fi

if [ -f "/var/lib/batman/CUSTOM_FIRSTPOLCORE" ]; then
   FIRSTPOLCORE="$(</var/lib/batman/CUSTOM_FIRSTPOLCORE)"
   echo "using ${FIRSTPOLCORE} as first policy core"
fi

# hotplug has to be disabled for cpu cores to be allowed to go offline on exynos chips (why? i don't know)
if [ "${IS_EXYNOS}" = "true" ]; then
   if [ -f /sys/power/cpuhotplug/enabled ]; then
      echo "0" > /sys/power/cpuhotplug/enabled
   fi
fi

[ "${CPUSAVEGOVERNOR}" = "exynos_cpu_limit" ] && RUNTIME_CUR_GOVERNOR="${DEFAULT_GOVERNOR}"

if [ -e "/proc/perfmgr/boost_ctrl/eas_ctrl/set_sched_deisolation" ] && [ -e "/proc/perfmgr/boost_ctrl/eas_ctrl/set_sched_isolation" ]; then
   echo "MTK isolation is available"
   MTK_ISOLATION=true
fi

# on some (if not all) exynos chips powersave doesn't exist so we need an alternative ways of lowering clock speeds
# like to set governor to userspace and set scaling_min_freq to scaling_setspeed to get the minimum frequency at idle.
if [ "${CPUSAVEGOVERNOR}" = "powersave" ]; then
    function powersave() {
        for ((i=CORE_FIRST; i<=CORE_LAST; i++))
        do
            echo "${CPUSAVEGOVERNOR}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor

            if [ "${MTK_ISOLATION}" = "true" ]; then
                echo $i > /proc/perfmgr/boost_ctrl/eas_ctrl/set_sched_isolation
            fi
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "userspace" ]; then
    function powersave() {
        for ((i=CORE_FIRST; i<=CORE_LAST; i++))
        do
            echo "${CPUSAVEGOVERNOR}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor
            MINFREQ="$(</sys/devices/system/cpu/cpu$i/cpufreq/scaling_min_freq)"
            echo "${MINFREQ}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_setspeed

            # the checks require powersave as saving governor as they were written back when that was the only supported governor
            # so we have to set this here to satisfy them
            RUNTIME_CUR_GOVERNOR="powersave"
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "exynos_cpu_limit" ]; then
    function powersave() {
        echo "${CPUFREQ_MIN_LIMIT}" > /sys/power/cpufreq_max_limit

        # same story as above applies here
        RUNTIME_CUR_GOVERNOR="powersave"
    }
else
    function powersave() {
        :
    }
fi

# same story as above basically
if [ "${CPUSAVEGOVERNOR}" = "powersave" ]; then
    function default() {
        for ((i=CORE_FIRST; i<=CORE_LAST; i++))
        do
            echo "${DEFAULT_GOVERNOR}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor

            if [ "${MTK_ISOLATION}" = "true" ]; then
                echo $i > /proc/perfmgr/boost_ctrl/eas_ctrl/set_sched_deisolation
            fi
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "userspace" ]; then
    function default() {
        for ((i=CORE_FIRST; i<=CORE_LAST; i++))
        do
            echo "${CPUSAVEGOVERNOR}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor
            MAXFREQ="$(</sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq)"
            echo "${MAXFREQ}" > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_setspeed

            # same thing as the powersave function of userspace governor
            RUNTIME_CUR_GOVERNOR="${DEFAULT_GOVERNOR}"
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "exynos_cpu_limit" ]; then
    function default() {
        echo "${CPUFREQ_MAX_LIMIT}" > /sys/power/cpufreq_max_limit
        echo "${CPUFREQ_MAX_LIMIT}" > /sys/power/cpufreq_min_limit

        # same thing as powersave function of exynos_cpu_limit governor
        RUNTIME_CUR_GOVERNOR="${DEFAULT_GOVERNOR}"
    }
else
    function default() {
       :
    }
fi

# some chipsets will crash the entire kernel if we set core 0 to offline so lets declare separate functions for them
if [ "${CPUSAVEGOVERNOR}" = "powersave" ] || [ "${CPUSAVEGOVERNOR}" = "userspace" ]; then
    function offline() {
        for ((i=FIRSTPOLCORE; i<=LASTPOLCORE; i++))
        do
             echo "0" > /sys/devices/system/cpu/cpu$i/online
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "exynos_cpu_limit" ]; then
    function offline() {
        for ((i=1; i<=LASTPOLCORE; i++))
        do
             echo "0" > /sys/devices/system/cpu/cpu$i/online
        done
    }
else
    function offline() {
       :
    }
fi

# same story as above but the opposite
if [ "${CPUSAVEGOVERNOR}" = "powersave" ] || [ "${CPUSAVEGOVERNOR}" = "userspace" ]; then
    function online() {
        for ((i=FIRSTPOLCORE; i<=LASTPOLCORE; i++))
        do
             echo "1" > /sys/devices/system/cpu/cpu$i/online
        done
    }
elif [ "${CPUSAVEGOVERNOR}" = "exynos_cpu_limit" ]; then
    function online() {
        # hotplug is unstable on devices with exynos_cpu_limit. if 0 goes down the kernel crashes.
        for ((i=1; i<=LASTPOLCORE; i++))
        do
             echo "1" > /sys/devices/system/cpu/cpu$i/online
        done
    }
else
    function online() {
       :
    }
fi

# TODO: figure out why most gpu governors just error out when writing to them (non critical)
function gpusave() {
   if [ "${GPUSAVE}" = "true" ] && [ "${CAN_GPUSAVE}" = "true" ]; then
      echo "powersave" > "${GPU_GOVERNOR_PATH}"
   fi
}

function gpudefault() {
   if [ "${GPUSAVE}" = "true" ] && [ "${CAN_GPUSAVE}" = "true" ]; then
      echo "${DEFAULT_GPU_GOVERNOR}" > "${GPU_GOVERNOR_PATH}"
   fi
}

# Check if BUSSAVE is enabled, if so enable use the right functions.
function bussave() {
   if [ "${BUSSAVE}" = "true" ]; then
      [ "${CCI}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cci/governor
      [ "${CPUBW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpubw/governor
      [ "${GPUBW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,gpubw/governor
      [ "${KGSL_BUSMON}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,kgsl-busmon/governor
      [ "${MINCPUBW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,mincpubw/governor
      # [ "${L3CPU0}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,l3-cpu0/governor
      # [ "${L3CPU6}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,l3-cpu6/governor
      [ "${VIDC1_ARM9_BUS_DDR}" = "true" ] && echo "powersave" > /sys/class/devfreq/aa00000.qcom,vidc1:arm9_bus_ddr/governor
      [ "${VIDC1_BUS_CNOC}" = "true" ] && echo "powersave" > /sys/class/devfreq/aa00000.qcom,vidc1:bus_cnoc/governor
      [ "${VIDC_ARM9_BUS_DDR}" = "true" ] && echo "powersave" > /sys/class/devfreq/aa00000.qcom,vidc:arm9_bus_ddr/governor
      [ "${VIDC_BUS_CNOC}" = "true" ] && echo "powersave" > /sys/class/devfreq/aa00000.qcom,vidc:bus_cnoc/governor
      # [ "${VENUS_BUS_DDR}" = "true" ] && echo "powersave" > /sys/class/devfreq/aa00000.qcom,vidc1:venus_bus_ddr/governor
      [ "${L3CDSP}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,l3-cdsp/governor
      [ "${MEMLAT_CPU0}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,memlat-cpu0/governor
      [ "${MEMLAT_CPU4}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,memlat-cpu4/governor
      [ "${MEMLAT_CPU6}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,memlat-cpu6/governor
      [ "${MINCPU0BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,mincpu0bw/governor
      [ "${MINCPU6BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,mincpu6bw/governor
      [ "${DEVFREQ_SPDM_CPU}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:devfreq_spdm_cpu/governor
      [ "${CDSP_CDSP_L3_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cdsp-cdsp-l3-lat/governor
      [ "${CPU0_CPU_DDR_LATFLOOR}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu0-cpu-ddr-latfloor/governor
      [ "${CPU0_CPU_L3_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu0-cpu-l3-lat/governor
      [ "${CPU0_CPU_LLCC_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu0-cpu-llcc-lat/governor
      [ "${CPU0_LLCC_DDR_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu0-llcc-ddr-lat/governor
      [ "${CPU6_CPU_DDR_LATFLOOR}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu6-cpu-ddr-latfloor/governor
      [ "${CPU6_CPU_L3_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu6-cpu-l3-lat/governor
      [ "${CPU6_CPU_LLCC_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu6-cpu-llcc-lat/governor
      [ "${CPU6_LLCC_DDR_LAT}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu6-llcc-ddr-lat/governor
      [ "${CPU_CPU_LLCC_BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/governor
      [ "${CPU_LLCC_DDR_BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/governor
      [ "${NPUDSP_NPU_DDR_BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,npudsp-npu-ddr-bw/governor
      [ "${NPU_NPU_DDR_BW}" = "true" ] && echo "powersave" > /sys/class/devfreq/soc:qcom,npu-npu-ddr-bw/governor
      [ "${DEVFREQ_MIF}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000010.devfreq_mif/governor
      [ "${DEVFREQ_INT}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000020.devfreq_int/governor
      [ "${DEVFREQ_INTCAM}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000030.devfreq_intcam/governor
      [ "${DEVFREQ_DISP}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000040.devfreq_disp/governor
      [ "${DEVFREQ_CAM}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000050.devfreq_cam/governor
      [ "${DEVFREQ_TNR}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000060.devfreq_tnr/governor
      [ "${DEVFREQ_MFC}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000070.devfreq_mfc/governor
      [ "${DEVFREQ_BO}" = "true" ] && echo "powersave" > /sys/class/devfreq/17000080.devfreq_bo/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU0}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu0_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU1}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu1_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU2}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu2_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU3}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu3_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU4}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu4_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU5}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu5_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU6}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu6_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU7}" = "true" ] && echo "powersave" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu7_memlat@17000010/governor
   fi

   :
}

function busdefault() {
   if [ "${BUSSAVE}" = "true" ]; then
      [ "${CCI}" = "true" ] && echo "${DEFAULT_CCI_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cci/governor
      [ "${CPUBW}" = "true" ] && echo "${DEFAULT_CPUBW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpubw/governor
      [ "${GPUBW}" = "true" ] && echo "${DEFAULT_GPUBW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,gpubw/governor
      [ "${KGSL_BUSMON}" = "true" ] && echo "${DEFAULT_KGSL_BUSMON_GOVERNOR}" > /sys/class/devfreq/soc:qcom,kgsl-busmon/governor
      [ "${MINCPUBW}" = "true" ] && echo "${DEFAULT_MINCPUBW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,mincpubw/governor
      # [ "${L3CPU0}" = "true" ] && echo "${DEFAULT_L3CPU0_GOVERNOR}" > /sys/class/devfreq/soc:qcom,l3-cpu0/governor
      # [ "${L3CPU6}" = "true" ] && echo "${DEFAULT_L3CPU6_GOVERNOR}" > /sys/class/devfreq/soc:qcom,l3-cpu6/governor
      [ "${VIDC1_ARM9_BUS_DDR}" = "true" ] && echo "${DEFAULT_VIDC1_ARM9_BUS_DDR_GOVERNOR}" > /sys/class/devfreq/aa00000.qcom,vidc1:arm9_bus_ddr/governor
      [ "${VIDC1_BUS_CNOC}" = "true" ] && echo "${DEFAULT_VIDC1_BUS_CNOC_GOVERNOR}" > /sys/class/devfreq/aa00000.qcom,vidc1:bus_cnoc/governor
      [ "${VIDC_ARM9_BUS_DDR}" = "true" ] && echo "${DEFAULT_VIDC_ARM9_BUS_DDR_GOVERNOR}" > /sys/class/devfreq/aa00000.qcom,vidc:arm9_bus_ddr/governor
      [ "${VIDC_BUS_CNOC}" = "true" ] && echo "${DEFAULT_VIDC_BUS_CNOC_GOVERNOR}" > /sys/class/devfreq/aa00000.qcom,vidc:bus_cnoc/governor
      # [ "${VENUS_BUS_DDR}" = "true" ] && echo "${DEFAULT_VENUS_BUS_DDR_GOVERNOR}" > /sys/class/devfreq/aa00000.qcom,vidc1:venus_bus_ddr/governor
      [ "${L3CDSP}" = "true" ] && echo "${DEFAULT_L3CDSP_GOVERNOR}" > /sys/class/devfreq/soc:qcom,l3-cdsp/governor
      [ "${MEMLAT_CPU0}" = "true" ] && echo "${DEFAULT_MEMLAT_CPU0_GOVERNOR}" > /sys/class/devfreq/soc:qcom,memlat-cpu0/governor
      [ "${MEMLAT_CPU4}" = "true" ] && echo "${DEFAULT_MEMLAT_CPU4_GOVERNOR}" > /sys/class/devfreq/soc:qcom,memlat-cpu4/governor
      [ "${MEMLAT_CPU6}" = "true" ] && echo "${DEFAULT_MEMLAT_CPU6_GOVERNOR}" > /sys/class/devfreq/soc:qcom,memlat-cpu6/governor
      [ "${MINCPU0BW}" = "true" ] && echo "${DEFAULT_MINCPU0BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,mincpu0bw/governor
      [ "${MINCPU6BW}" = "true" ] && echo "${DEFAULT_MINCPU6BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,mincpu6bw/governor
      [ "${DEVFREQ_SPDM_CPU}" = "true" ] && echo "${DEFAULT_DEVFREQ_SPDM_CPU_GOVERNOR}" > /sys/class/devfreq/soc:devfreq_spdm_cpu/governor
      [ "${CDSP_CDSP_L3_LAT}" = "true" ] && echo "${DEFAULT_CDSP_CDSP_L3_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cdsp-cdsp-l3-lat/governor
      [ "${CPU0_CPU_DDR_LATFLOOR}" = "true" ] && echo "${DEFAULT_CPU0_CPU_DDR_LATFLOOR_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu0-cpu-ddr-latfloor/governor
      [ "${CPU0_CPU_L3_LAT}" = "true" ] && echo "${DEFAULT_CPU0_CPU_L3_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu0-cpu-l3-lat/governor
      [ "${CPU0_CPU_LLCC_LAT}" = "true" ] && echo "${DEFAULT_CPU0_CPU_LLCC_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu0-cpu-llcc-lat/governor
      [ "${CPU0_LLCC_DDR_LAT}" = "true" ] && echo "${DEFAULT_CPU0_LLCC_DDR_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu0-llcc-ddr-lat/governor
      [ "${CPU6_CPU_DDR_LATFLOOR}" = "true" ] && echo "${DEFAULT_CPU6_CPU_DDR_LATFLOOR_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu6-cpu-ddr-latfloor/governor
      [ "${CPU6_CPU_L3_LAT}" = "true" ] && echo "${DEFAULT_CPU6_CPU_L3_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu6-cpu-l3-lat/governor
      [ "${CPU6_CPU_LLCC_LAT}" = "true" ] && echo "${DEFAULT_CPU6_CPU_LLCC_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu6-cpu-llcc-lat/governor
      [ "${CPU6_LLCC_DDR_LAT}" = "true" ] && echo "${DEFAULT_CPU6_LLCC_DDR_LAT_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu6-llcc-ddr-lat/governor
      [ "${CPU_CPU_LLCC_BW}" = "true" ] && echo "${DEFAULT_CPU_CPU_LLCC_BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/governor
      [ "${CPU_LLCC_DDR_BW}" = "true" ] && echo "${DEFAULT_CPU_LLCC_DDR_BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/governor
      [ "${NPUDSP_NPU_DDR_BW}" = "true" ] && echo "${DEFAULT_NPUDSP_NPU_DDR_BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,npudsp-npu-ddr-bw/governor
      [ "${NPU_NPU_DDR_BW}" = "true" ] && echo "${DEFAULT_NPU_NPU_DDR_BW_GOVERNOR}" > /sys/class/devfreq/soc:qcom,npu-npu-ddr-bw/governor
      [ "${DEVFREQ_MIF}" = "true" ] && echo "${DEFAULT_DEVFREQ_MIF_GOVERNOR}" > /sys/class/devfreq/17000010.devfreq_mif/governor
      [ "${DEVFREQ_INT}" = "true" ] && echo "${DEFAULT_DEVFREQ_INT_GOVERNOR}" > /sys/class/devfreq/17000020.devfreq_int/governor
      [ "${DEVFREQ_INTCAM}" = "true" ] && echo "${DEFAULT_DEVFREQ_INTCAM_GOVERNOR}" > /sys/class/devfreq/17000030.devfreq_intcam/governor
      [ "${DEVFREQ_DISP}" = "true" ] && echo "${DEFAULT_DEVFREQ_DISP_GOVERNOR}" > /sys/class/devfreq/17000040.devfreq_disp/governor
      [ "${DEVFREQ_CAM}" = "true" ] && echo "${DEFAULT_DEVFREQ_CAM_GOVERNOR}" > /sys/class/devfreq/17000050.devfreq_cam/governor
      [ "${DEVFREQ_TNR}" = "true" ] && echo "${DEFAULT_DEVFREQ_TNR_GOVERNOR}" > /sys/class/devfreq/17000060.devfreq_tnr/governor
      [ "${DEVFREQ_MFC}" = "true" ] && echo "${DEFAULT_DEVFREQ_MFC_GOVERNOR}" > /sys/class/devfreq/17000070.devfreq_mfc/governor
      [ "${DEVFREQ_BO}" = "true" ] && echo "${DEFAULT_DEVFREQ_BO_GOVERNOR}" > /sys/class/devfreq/17000080.devfreq_bo/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU0}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU0_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu0_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU1}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU1_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu1_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU2}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU2_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu2_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU3}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU3_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu3_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU4}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU4_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu4_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU5}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU5_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu5_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU6}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU6_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu6_memlat@17000010/governor
      [ "${GS_MEMLAT_DEVFREQ_MIF_CPU7}" = "true" ] && echo "${DEFAULT_GS_MEMLAT_DEVFREQ_MIF_CPU7_GOVERNOR}" > /sys/class/devfreq/gs_memlat_devfreq:devfreq_mif_cpu7_memlat@17000010/governor
   fi

   :
}

function btsave {
   if [ "${BTSAVE}" = "true" ]; then
      if [ "${BTSTAT}" = "on" ]; then
         if ! bluetoothctl info | grep -q 'Connected:'; then
            bluetoothctl power off > /dev/null 2>&1 &
            BTSTAT="off"
         fi
      fi
   fi
}

function btdefault {
   if [ "${BTSAVE}" = "true" ] && [ "${BTSTAT}" = "off" ]; then
      bluetoothctl power on > /dev/null 2>&1 &
      BTSTAT="on"
   fi
}

function tweakboost {
   [ -f /proc/cpufreq/cpufreq_power_mode ] && echo 3 > /proc/cpufreq/cpufreq_power_mode # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_cci_mode ] && echo 1 > /proc/cpufreq/cpufreq_cci_mode # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_sched_disable ] && echo 0 > /proc/cpufreq/cpufreq_sched_disable # spotted on mt6769v
   [ -f /sys/devices/system/cpu/perf/enable ] && echo 1 > /sys/devices/system/cpu/perf/enable # spotted on mt6769v
   [ -f /sys/devices/system/cpu/sched/sched_boost ] && echo 1 > /sys/devices/system/cpu/sched/sched_boost # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_stress_test ] && echo 1 > /proc/cpufreq/cpufreq_stress_test # spotted on mt6769v
   [ -f /sys/module/ged/parameters/boost_gpu_enable ] && echo 1 > /sys/module/ged/parameters/boost_gpu_enable # spotted on mt6769v
   [ -f /sys/module/ged/parameters/boost_extra ] && echo 1 > /sys/module/ged/parameters/boost_extra # spotted on mt6769v
   [ -f /sys/module/ged/parameters/gx_game_mode ] && echo 1 > /sys/module/ged/parameters/gx_game_mode # spotted on mt6769v
   [ -f /sys/module/ged/parameters/gx_boost_on ] && echo 1 > /sys/module/ged/parameters/gx_boost_on # spotted on mt6769v
   [ -f /sys/kernel/gbe/gbe_enable1 ] && echo 1 > /sys/kernel/gbe/gbe_enable1 # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe_enable2 ] && echo 1 > /sys/kernel/gbe/gbe_enable2 # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe2_max_boost_cnt ] && echo 2 > /sys/kernel/gbe/gbe2_max_boost_cnt # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe2_loading_th ] && echo 20 > /sys/kernel/gbe/gbe2_loading_th # spotted on mt6789
   [ -f /sys/module/ged/parameters/ged_force_mdp_enable ] && echo 1 > /sys/module/ged/parameters/ged_force_mdp_enable # spotted on mt6789
   [ -f /sys/module/lpm_levels/parameters/sleep_disabled ] && echo Y > /sys/module/lpm_levels/parameters/sleep_disabled # spotted on msm8996 and sm7125
   [ -f /sys/module/lpm_levels/parameters/lpm_prediction ] && echo N > /sys/module/lpm_levels/parameters/lpm_prediction # spotted on sm7125
   [ -f /sys/module/lpm_levels/parameters/lpm_ipi_prediction ] && echo N > /sys/module/lpm_levels/parameters/lpm_ipi_prediction # spotted on sm7125
   [ -f /sys/kernel/debug/msm_vidc/fw_low_power_mode ] && echo 0 > /sys/kernel/debug/msm_vidc/fw_low_power_mode # spotted on msm8996 and sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/hibern8_on_idle_enable ] && echo 0 > /sys/devices/platform/soc/1d84000.ufshc/hibern8_on_idle_enable # spotted on sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/clkgate_enable ] && echo 0 > /sys/devices/platform/soc/1d84000.ufshc/clkgate_enable # spotted on sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/clkscale_enable ] && echo 0 > /sys/devices/platform/soc/1d84000.ufshc/clkscale_enable # spotted on sm7125
   [ -f /proc/cpufreq/MT_CPU_DVFS_CCI/cpufreq_turbo_mode ] && echo 1 > /proc/cpufreq/MT_CPU_DVFS_CCI/cpufreq_turbo_mode # spotted on mt6877
   [ -f /proc/cpufreq/MT_CPU_DVFS_L/cpufreq_turbo_mode ] && echo 1 > /proc/cpufreq/MT_CPU_DVFS_L/cpufreq_turbo_mode # spotted on mt6877
   [ -f /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_turbo_mode ] && echo 1 > /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_turbo_mode # spotted on mt6877
   [ -f /sys/module/ged/parameters/boost_amp ] && echo 1 > /sys/module/ged/parameters/boost_amp # spotted on mt6877
   [ -f /proc/perfmgr/boost_ctrl/dram_ctrl/ddr ] && echo 2 > /proc/perfmgr/boost_ctrl/dram_ctrl/ddr # spotted on mt6877
   [ -f /sys/kernel/fpsgo/fstb/adopt_low_fps ] && echo 0 > /sys/kernel/fpsgo/fstb/adopt_low_fps # spotted on mt6877
   [ -f /sys/kernel/fpsgo/fbt/boost_ta ] && echo 1 > /sys/kernel/fpsgo/fbt/boost_ta # spotted on mt6877
   [ -f /sys/kernel/fpsgo/common/gpu_block_boost ] && echo 101 > /sys/kernel/fpsgo/common/gpu_block_boost # spotted on mt6877
   [ -f /sys/kernel/apusys/mnoc_apu_qos_boost ] && echo 1 > /sys/kernel/apusys/mnoc_apu_qos_boost # spotted on mt6877
   [ -f /proc/perfmgr/boost_ctrl/eas_ctrl/sched_boost ] && echo 1 > /proc/perfmgr/boost_ctrl/eas_ctrl/sched_boost # spotted on mt6877

   :
}

function tweaksave {
   [ -f /proc/cpufreq/cpufreq_power_mode ] && echo 1 > /proc/cpufreq/cpufreq_power_mode # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_cci_mode ] && echo 0 > /proc/cpufreq/cpufreq_cci_mode # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_sched_disable ] && echo 1 > /proc/cpufreq/cpufreq_sched_disable # spotted on mt6769v
   [ -f /sys/devices/system/cpu/perf/enable ] && echo 0 > /sys/devices/system/cpu/perf/enable # spotted on mt6769v
   [ -f /sys/devices/system/cpu/sched/sched_boost ] && echo 0 > /sys/devices/system/cpu/sched/sched_boost # spotted on mt6769v
   [ -f /proc/cpufreq/cpufreq_stress_test ] && echo 0 > /proc/cpufreq/cpufreq_stress_test # spotted on mt6769v
   [ -f /sys/module/ged/parameters/boost_gpu_enable ] && echo 0 > /sys/module/ged/parameters/boost_gpu_enable # spotted on mt6769v
   [ -f /sys/module/ged/parameters/boost_extra ] && echo 0 > /sys/module/ged/parameters/boost_extra # spotted on mt6769v
   [ -f /sys/module/ged/parameters/gx_game_mode ] && echo 0 > /sys/module/ged/parameters/gx_game_mode # spotted on mt6769v
   [ -f /sys/module/ged/parameters/gx_boost_on ] && echo 0 > /sys/module/ged/parameters/gx_boost_on # spotted on mt6769v
   [ -f /sys/kernel/gbe/gbe_enable1 ] && echo 0 > /sys/kernel/gbe/gbe_enable1 # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe_enable2 ] && echo 0 > /sys/kernel/gbe/gbe_enable2 # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe2_max_boost_cnt ] && echo 2 > /sys/kernel/gbe/gbe2_max_boost_cnt # spotted on mt6789
   [ -f /sys/kernel/gbe/gbe2_loading_th ] && echo 5 > /sys/kernel/gbe/gbe2_loading_th # spotted on mt6789
   [ -f /sys/module/ged/parameters/ged_force_mdp_enable ] && echo 1 > /sys/module/ged/parameters/ged_force_mdp_enable # spotted on mt6789
   [ -f /sys/module/lpm_levels/parameters/sleep_disabled ] && echo N > /sys/module/lpm_levels/parameters/sleep_disabled  # spotted on msm8996 and sm7125
   [ -f /sys/module/lpm_levels/parameters/lpm_prediction ] && echo N > /sys/module/lpm_levels/parameters/lpm_prediction # spotted on sm7125
   [ -f /sys/module/lpm_levels/parameters/lpm_ipi_prediction ] && echo N > /sys/module/lpm_levels/parameters/lpm_ipi_prediction # spotted on sm7125
   [ -f /sys/kernel/debug/msm_vidc/fw_low_power_mode ] && echo 1 > /sys/kernel/debug/msm_vidc/fw_low_power_mode # spotted on msm8996 and sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/hibern8_on_idle_enable ] && echo 1 > /sys/devices/platform/soc/1d84000.ufshc/hibern8_on_idle_enable # spotted on sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/clkgate_enable ] && echo 1 > /sys/devices/platform/soc/1d84000.ufshc/clkgate_enable # spotted on sm7125
   [ -f /sys/devices/platform/soc/1d84000.ufshc/clkscale_enable ] && echo 1 > /sys/devices/platform/soc/1d84000.ufshc/clkscale_enable # spotted on sm7125
   [ -f /proc/cpufreq/MT_CPU_DVFS_CCI/cpufreq_turbo_mode ] && echo 0 > /proc/cpufreq/MT_CPU_DVFS_CCI/cpufreq_turbo_mode # spotted on mt6877
   [ -f /proc/cpufreq/MT_CPU_DVFS_L/cpufreq_turbo_mode ] && echo 0 > /proc/cpufreq/MT_CPU_DVFS_L/cpufreq_turbo_mode # spotted on mt6877
   [ -f /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_turbo_mode ] && echo 0 > /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_turbo_mode # spotted on mt6877
   [ -f /sys/module/ged/parameters/boost_amp ] && echo 0 > /sys/module/ged/parameters/boost_amp # spotted on mt6877
   [ -f /proc/perfmgr/boost_ctrl/dram_ctrl/ddr ] && echo 0 > /proc/perfmgr/boost_ctrl/dram_ctrl/ddr # spotted on mt6877
   [ -f /sys/kernel/fpsgo/fstb/adopt_low_fps ] && echo 1 > /sys/kernel/fpsgo/fstb/adopt_low_fps # spotted on mt6877
   [ -f /sys/kernel/fpsgo/fbt/boost_ta ] && echo 0 > /sys/kernel/fpsgo/fbt/boost_ta # spotted on mt6877
   [ -f /sys/kernel/fpsgo/common/gpu_block_boost ] && echo 0 > /sys/kernel/fpsgo/common/gpu_block_boost # spotted on mt6877
   [ -f /sys/kernel/apusys/mnoc_apu_qos_boost ] && echo 0 > /sys/kernel/apusys/mnoc_apu_qos_boost # spotted on mt6877
   [ -f /proc/perfmgr/boost_ctrl/eas_ctrl/sched_boost ] && echo 0 > /proc/perfmgr/boost_ctrl/eas_ctrl/sched_boost # spotted on mt6877

   :
}

echo "" > /var/lib/batman/screen

chown -R "${UIDS}":"${UIDS}" /var/lib/batman

while true
do
    SCREEN_OLD="$(</var/lib/batman/screen)"

    CPU_USAGE=$(batman-helper cpu)

    SCREEN=$(eval "${GET_SCREEN}")

    if [ "${KDE}" = "true" ]; then
        if [ "${SCREEN}" = "true" ]; then
           SCREEN="no"
        else
           SCREEN="yes"
        fi
    fi

    if [ "${CHARGESAVE}" = "true" ]; then
        CHARGE="discharging"
    else
        CHARGE=$(batman-helper battery)
    fi

    # an attempt to fix choppy audio when system goes to sleep by lowering the number of cores that go offline if there is an audio playing
    if ! [ "${ARCH}" = "x86_64" ] && ! [ "${ARCH}" = "i686" ]; then
        if cat /proc/asound/card*/pcm*/sub*/status | grep -q RUNNING; then
            if [ "${LASTPOLCORE}" -ge "${OFFLINE_COUNT}" ]; then
                LASTPOLCORE=$((LASTPOLCORE/2))
                if [ "${OFFLINE}" = "true" ] && [ "${SCREEN}" = "no" ]; then
                    LASTPOLCORE_TMP="${LASTPOLCORE}"
                    LASTPOLCORE="${OFFLINE_COUNT}"
                    online
                    LASTPOLCORE="${LASTPOLCORE_TMP}"
                    delay 0.3
                    offline
                fi
            fi
        fi
    fi

    if [ "${SCREEN}" = yes ]; then
        LASTPOLCORE="${OFFLINE_COUNT}"
    fi

    # on x86 devices mostly operate in powersave anyways so we should check
    # if device is plugged into a power source then set the governor to performance
    if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
       if [ "${CHARGE}" = "charging" ] || [ "${CHARGE}" = "fully-charged" ]; then
          DEFAULT_GOVERNOR="performance"
       else
          DEFAULT_GOVERNOR="powersave"
       fi
    fi

    if [ "${POWERSAVE}" = "true" ]; then
       # if screen is off and device is not charging then device will be set into powersave.
       if [ "${SCREEN_OLD}" != "${SCREEN}" ] && [ "${CHARGE}" = "discharging" ] && [ "${SCREEN}" = "no" ]; then
          powersave
          gpusave
          bussave
          btsave
          tweaksave

          [ "${WAYDROID}" == "true" ] && (batman-waydroid screen 0 &)
          [ "${LIBPOWER}" = "true" ] && batman-hybris power 0
          [ "${WIFI}" = "true" ] && batman-wifi suspend
       # if device is charging or fully charged and still plugged into the wall then set everything back to default. this behaviour can be changed by setting CHARGESAVE to true.
       elif [ "${SCREEN_OLD}" != "$SCREEN" ] && [ "${CHARGE}" = "charging" ] || [ "${CHARGE}" = "fully-charged" ]; then
          default
          gpudefault
          busdefault
          btdefault
          tweakboost

          [ "${WAYDROID}" == "true" ] && (batman-waydroid screen 1 &)
          [ "${LIBPOWER}" = "true" ] && batman-hybris power 1
          [ "${WIFI}" = "true" ] && batman-wifi resume
       # if screen is on (user using the device) set everything back to default.
       elif [ "${SCREEN}" = "yes" ]; then
          default
          gpudefault
          busdefault
          btdefault
          tweakboost

          [ "${WAYDROID}" == "true" ] && (batman-waydroid screen 1 &)
          [ "${LIBPOWER}" = "true" ] && batman-hybris power 1
          [ "${WIFI}" = "true" ] && batman-wifi resume
       fi
    fi

    # Save the current governor (check what has happened in the last run) so that if it is set to powersave we can use this info in our cpu offlining.
    if [ -z "${RUNTIME_CUR_GOVERNOR}" ]; then
       CUR_GOVERNOR="$(</sys/devices/system/cpu/cpu"${CORE_FIRST}"/cpufreq/scaling_governor)"
    else
       CUR_GOVERNOR="${RUNTIME_CUR_GOVERNOR}"
    fi

    if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
       if [ "${SCREEN}" = "no" ]; then
          SCREEN_OLD=yes
       fi

       DEFAULT_GOVERNOR="performance"
       CHARGE='discharging'
    fi

    if [ "${OFFLINE}" = "true" ]; then
       # if device is not plugged into a power source and screen is off and cpu usage is less than MAX_CPU_USAGE (default is 60) then set cpu to offline.
       if [ "${SCREEN_OLD}" != "${SCREEN}" ] && [ "${CHARGE}" = "discharging" ] && [ "${SCREEN}" = "no" ] && [ "${CPU_USAGE}" -le "${MAX_CPU_USAGE}" ]; then
          offline
       # if screen or on or current governor is the same as default governor or cpu usage is higher than MAX_CPU_USAGE (default is 60) set cpu cores to online.
       elif [ "${SCREEN}" = "yes" ] || [ "${CUR_GOVERNOR}" = "${DEFAULT_GOVERNOR}" ] || [ "${CPU_USAGE}" -gt "${MAX_CPU_USAGE}" ]; then
          online
       # if device is powersave (which means device is sleeping) then set cpu cores to offline.
       elif [ "${SCREEN_OLD}" = "${SCREEN}" ] && [ "${CUR_GOVERNOR}" = "powersave" ]; then
          offline
       fi
    fi

    if [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "i686" ]; then
       # on x86 chips batman will be intrerrupted if device gets suspended but we can fix this by checking if we can read a file
       # that is usually unavailable when cpu cores are set to offline and set the status accordingly to leave that unexpected state.
       if [ "${SCREEN}" = "yes" ]; then
          if ! cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor > /dev/null 2>&1; then
             online
             default
             gpudefault
             busdefault
          fi
       fi
    fi

    if [ "${SCREEN_OLD}" != "${SCREEN}" ]; then
       echo "${SCREEN}" > /var/lib/batman/screen
    fi

    if ! [ "${ARCH}" = "x86_64" ] && ! [ "${ARCH}" = "i686" ]; then
        if ! cat /proc/asound/card*/pcm*/sub*/status | grep -q RUNNING; then
            LASTPOLCORE="${OFFLINE_COUNT}"
        fi
    fi

    # To not do as many useless iterations wait here for some time when the screen is on or when user is using the device.
    if [ "${SCREEN}" = "yes" ]; then
       if [ "${SCREEN_OLD}" = "no" ]; then
          delay 0.3
       else
          delay 10
          source <(tail -n +2 "${CONFIG_FILE}")
       fi
    else
       delay 0.3
    fi
done
